﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Ingr.SP3D.Common;
using Ingr.SP3D.Common.Middle;
using System.Data;
using Ingr.SP3D.Route.Middle;
using Ingr.SP3D.Common.Middle.Services.Hidden;
using Ingr.SP3D.Common.Client.Services;
using System.Data.SqlClient;
using TMPipeTopology;
using SWS.PIP.DM;
using Ingr.SP3D.Planning.Middle;
using System.Configuration;
using GscadGraphicEntityMgr;
using Ingr.SP3D.Common.Middle.Services;
using Ingr.SP3D.Systems.Middle;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace SWS.PIP.CMD
{
	

	public class ParentAss
	{
		public string Name { get; set; }
		public string OID { get; set; }

		public override bool Equals(object obj)
		{
			ParentAss assNode = obj as ParentAss;
			return (Name == assNode.Name) && (OID == assNode.OID);
		}

		public override int GetHashCode()
		{
			return base.GetHashCode();
		}
	}

	public class SMngtSpoolComparer : IEqualityComparer<SMgnt_SpoolInfo>
	{
		public static SMngtSpoolComparer Default = new SMngtSpoolComparer();

		#region IEqualityComparer<SMgnt_SpoolInfo> 成员  
		public bool Equals(SMgnt_SpoolInfo x, SMgnt_SpoolInfo y)
		{
			return x.Spool.Equals(y.Spool) || (x.Zone == y.Zone && x.Block == y.Block && x.Spool_oid == y.Spool_oid);
		}

		public int GetHashCode(SMgnt_SpoolInfo obj)
		{
			return obj.GetHashCode();
		}
		#endregion
	}

	class CommonFunctions
	{
		/// <summary>
		/// 获取指定装配节点下所有的Spool对象
		/// </summary>
		/// <param name="oAssmNode"></param>
		/// <returns></returns>
		public static List<BusinessObject> GetAllSpoolFromAssmNode(BusinessObject oAssmNode)
		{
			List<BusinessObject> oSpools = new List<BusinessObject>();

			IAssembly oAssm = oAssmNode as IAssembly;
			if (oAssm == null)
			{
				throw new Exception($"输入对象{oAssmNode.ToString()}{oAssmNode.ObjectID}类型非装配对象。");
			}


			GetAssemblyChildrenByType(oAssmNode, typeof(PipeSpool), ref oSpools);

			////排除空小票
			//List<BusinessObject> oNonNullSpools = new List<BusinessObject>();
			//foreach(var ospool in oSpools)
			//{
			//	IAssembly oAssembly = ospool as IAssembly;
			//	if (oAssembly != null && oAssembly.AssemblyChildren.Count != 0)
			//		oNonNullSpools.Add(ospool);
			//}
			return oSpools;
			//return oNonNullSpools;
		}

		public static void GetAssemblyChildrenByType(BusinessObject oAssmParent, Type oType, ref List<BusinessObject> oChildren)
		{
			IAssembly oAssm = oAssmParent as IAssembly;

			if (oAssm == null || oAssm.AssemblyChildren == null)
				return;

			foreach (var child in oAssm.AssemblyChildren)
			{
				if (child.GetType() == oType)
				{
					oChildren.Add(child as BusinessObject);
				}
				else
				{
					//Type type = child.GetType();
					//GetAssemblyChildrenByType(child as BusinessObject, oType, ref oChildren);
				}
			}
		}

		public static DataTable GetSpoolNameTable(List<BusinessObject> oSpools)
		{
			DataTable oTable = new DataTable();
			oTable.Columns.Add("Name", typeof(string));
			oTable.Columns.Add("oid", typeof(string));
			oTable.Columns.Add("object", typeof(BusinessObject));

			foreach (var spool in oSpools)
			{
				DataRow row = oTable.NewRow();
				row["Name"] = spool.ToString();
				row["oid"] = spool.ObjectID;
				row["object"] = spool;
				oTable.Rows.Add(row);
			}

			return oTable;
		}

		/// <summary>
		/// 初始化管小票管理功能相关数据库（新建表格）
		/// </summary>
		/// <param name="sDBName"></param>
		public static void InitialSpoolMgntDatabase(string sDBName)
		{
			//连接到db
			//SQLDBConnection dbConn = new SQLDBConnection(ClientServiceProvider.WorkingSet.ActiveConnection.Server, sDBName);
			//SqlConnection conn = dbConn.Connection;

			SqlConnection conn = SQLDBConnectionHelper.GetSqlConnection();
			if (conn.State != ConnectionState.Open)
				conn.Open();

			//判断数据库是否存在，不存在则创建数据表
			//SpoolInfo
			string sSql = $"select * from sysobjects where name='SMgnt_SpoolInfo'";
			SqlCommand cmd = new SqlCommand(sSql, conn);
			if (cmd.ExecuteScalar() == null)
			{
				sSql = @"create table [dbo].[SMgnt_SpoolInfo](
							Spool_oid nvarchar(50) NOT NULL,
							CalculateCode nvarchar(3000) NOT NULL,
							Spool nvarchar(50) NOT NULL,
							DrawNo nvarchar(50) DEFAULT(''),
							PageNo nvarchar(50) DEFAULT(''),
							Major nvarchar(50) NOT NULL,
							Zone nvarchar(50) NOT NULL,
							Block nvarchar(50) NOT NULL,
							Block_oid nvarchar(50) NOT NULL,
							ParentAss nvarchar(50) NOT NULL,
							ParentAss_oid nvarchar(50) NOT NULL,
							Name nvarchar(50) NOT NULL,
							Weight numeric(18, 4) DEFAULT(0),
							Type nvarchar(50) DEFAULT(''),
							GroupType nvarchar(50) DEFAULT(''),
							SpecName nvarchar(50) DEFAULT(''),
							TestPressure nvarchar(50) DEFAULT(''),
							InnerTreatment nvarchar(50) DEFAULT(''),
							OutterTreatment nvarchar(50) DEFAULT(''),
							StartInfo nvarchar(50) DEFAULT(''),
							EndInfo nvarchar(50) DEFAULT(''),
							PipeLineSystemPath nvarchar(200) DEFAULT(''),
							SpoolPath nvarchar(200) DEFAULT(''),
							ModificationFileCode nvarchar(50) DEFAULT(''),
							CreateBy nvarchar(50) DEFAULT(''),
							SpoolStatus nvarchar(50) DEFAULT(''),
							StringAssemblyInfo nvarchar(2000) DEFAULT(''),
							StringPipeBendInfo nvarchar(2000) DEFAULT(''),
							StringPipeCheckInfo nvarchar(2000) DEFAULT(''),
							StringPipePartInfo nvarchar(4000) DEFAULT(''),
							StringPipeSpoolInfo nvarchar(2000) DEFAULT(''),
							StringPipeWeldInfo nvarchar(2000) DEFAULT(''),
							StringStartEndInfo nvarchar(100) DEFAULT(''),
							IsBendPipe int DEFAULT(0),
							IsValid int DEFAULT(1),
							PlusSpoolDescription nvarchar(256) DEFAULT(''),
							PlusSpoolMaterialGrade nvarchar(50) DEFAULT(''),
							PlusSpoolClass nvarchar(50) DEFAULT(''),
							PlusIsSRTP int DEFAULT(0),
							PlusProductionLine nvarchar(50) DEFAULT(''),
							PlusInnerSurfaceArea numeric(18, 4) DEFAULT(0),
							PlusOuterSurfaceArea numeric(18, 4) DEFAULT(0),
							PlusSpoolLength numeric(18, 4) DEFAULT(0),
							PlusSpoolNPD numeric(18, 4) DEFAULT(0),
							PlusSpoolPOD numeric(18, 4) DEFAULT(0),
							PlusSpoolWallThickness numeric(18, 4) DEFAULT(0),
							PlusWBS nvarchar(50) DEFAULT(''),
							CreateTime datetime DEFAULT CURRENT_TIMESTAMP,
							UpdateTime datetime DEFAULT CURRENT_TIMESTAMP
						CONSTRAINT [PK_SMgnt_SpoolInfo] PRIMARY KEY CLUSTERED 
							(
							Spool_oid
							) WITH(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
						) ON [PRIMARY]";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();

				sSql = @"create trigger SMgnt_SpoolInfo_trig_updateTime
						on [dbo].[SMgnt_SpoolInfo]
						after INSERT, UPDATE
						as
						begin
							declare @updateId nvarchar(50)
							select @updateId=Spool_oid from inserted  
							update [dbo].[SMgnt_SpoolInfo] set [UpdateTime]=getdate() from [dbo].[SMgnt_SpoolInfo] where Spool_oid = @updateId
						end";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();
			}

			//PipePart
			sSql = $"select * from sysobjects where name='SMgnt_PipePart'";
			cmd = new SqlCommand(sSql, conn);
			if (cmd.ExecuteScalar() == null)
			{
				sSql = @"CREATE TABLE [dbo].[SMgnt_PipePart](
						Part_oid nvarchar(50) NOT NULL,
						Spool_oid nvarchar(50) NOT NULL,
						Spool nvarchar(50) NOT NULL,
						Tag nvarchar(50) DEFAULT(''),
						MatCode nvarchar(50) DEFAULT(''),
						MatDesc nvarchar(500) DEFAULT(''),
						GeometryStd nvarchar(50) DEFAULT(''),
						EndCut nvarchar(50) DEFAULT(''),
						Qty numeric(18, 4) DEFAULT(0),
						QtyDesc nvarchar(50) DEFAULT(''),
						Priority nvarchar(50) DEFAULT(''),
						BendPlus numeric(18, 4) DEFAULT(0),
						ModelLen numeric(18, 4) DEFAULT(0),
						Weight numeric(18, 4) DEFAULT(0),
						Class int DEFAULT(0),
						CreateTime datetime DEFAULT CURRENT_TIMESTAMP,
						UpdateTime datetime DEFAULT CURRENT_TIMESTAMP
						CONSTRAINT [PK_SMgnt_PipePart] PRIMARY KEY CLUSTERED 
						(
						Part_oid
						) WITH(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
						CONSTRAINT [FK_SMgnt_PipePart_SMgnt_SpoolInfo] FOREIGN KEY
						(
						[Spool_oid]
						) REFERENCES [dbo].[SMgnt_SpoolInfo]
						(
						Spool_oid
						) ON UPDATE  CASCADE 
						ON DELETE  CASCADE 
						) ON [PRIMARY]";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();

				sSql = @"create trigger SMgnt_PipePart_trig_updateTime
						on [dbo].[SMgnt_PipePart]
						after INSERT, UPDATE
						as
						begin
							declare @updateId nvarchar(50)
							select @updateId=Part_oid from inserted  
							update [dbo].[SMgnt_PipePart] set [UpdateTime]=getdate() from [dbo].[SMgnt_PipePart] where Part_oid = @updateId
						end";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();
			}

			//PipeWeld
			sSql = $"select * from sysobjects where name='SMgnt_PipeWeld'";
			cmd = new SqlCommand(sSql, conn);
			if (cmd.ExecuteScalar() == null)
			{
				sSql = @"CREATE TABLE [dbo].[SMgnt_PipeWeld](
						Weld_oid nvarchar(50) NOT NULL,
						Spool_oid nvarchar(50) NOT NULL,
						Spool nvarchar(50) NOT NULL,
						Tag nvarchar(50) DEFAULT(''),
						Type nvarchar(50) DEFAULT(''),
						Code nvarchar(50) DEFAULT(''),
						Size nvarchar(50) DEFAULT(''),
						Thickness nvarchar(50) DEFAULT(''),
						Conn nvarchar(200) DEFAULT(''),
						ConnDesc nvarchar(200) DEFAULT(''),
						PipeGrade nvarchar(50) DEFAULT(''),
						Stage nvarchar(50) DEFAULT(''),
						CreateTime datetime DEFAULT CURRENT_TIMESTAMP,
						UpdateTime datetime DEFAULT CURRENT_TIMESTAMP
						CONSTRAINT [PK_SMgnt_PipeWeld] PRIMARY KEY CLUSTERED 
						(
						Weld_oid
						) WITH(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
						CONSTRAINT [FK_SMgnt_PipeWeld_SMgnt_SpoolInfo] FOREIGN KEY
						(
						[Spool_oid]
						) REFERENCES [dbo].[SMgnt_SpoolInfo]
						(
						Spool_oid
						) ON UPDATE  CASCADE 
						ON DELETE  CASCADE 
						) ON [PRIMARY]";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();

				sSql = @"create trigger SMgnt_PipeWeld_trig_updateTime
						on [dbo].[SMgnt_PipeWeld]
						after INSERT, UPDATE
						as
						begin
							declare @updateId nvarchar(50)
							select @updateId=Weld_oid from inserted  
							update [dbo].[SMgnt_PipeWeld] set [UpdateTime]=getdate() from [dbo].[SMgnt_PipeWeld] where Weld_oid = @updateId
						end";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();

			}

			//PipeBend
			sSql = $"select * from sysobjects where name='SMgnt_PipeBend'";
			cmd = new SqlCommand(sSql, conn);
			if (cmd.ExecuteScalar() == null)
			{
				sSql = @"CREATE TABLE [dbo].[SMgnt_PipeBend](
						Id bigint NOT NULL IDENTITY (1, 1),
						Spool_oid nvarchar(50) NOT NULL,
						Spool nvarchar(50) NOT NULL,
						TurnFeature_oid nvarchar(50) NOT NULL,
						Part_oid nvarchar(50) NOT NULL,
						Tag nvarchar(50) DEFAULT(''),
						PullLen nvarchar(50) DEFAULT(''),
						BendRadius nvarchar(50) DEFAULT(''),
						BendAngle nvarchar(50) DEFAULT(''),
						TurnAngle nvarchar(50) DEFAULT(''),
						CutLen nvarchar(50) DEFAULT(''),
						BendStartLen nvarchar(50) DEFAULT(''),
						TailCutLen nvarchar(50) DEFAULT(''),
						CreateTime datetime DEFAULT CURRENT_TIMESTAMP,
						UpdateTime datetime DEFAULT CURRENT_TIMESTAMP
						CONSTRAINT [PK_SMgnt_PipeBend] PRIMARY KEY CLUSTERED 
						(
						Id
						) WITH(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
						CONSTRAINT [FK_SMgnt_PipeBend_SMgnt_SpoolInfo] FOREIGN KEY
						(
						[Spool_oid]
						) REFERENCES [dbo].[SMgnt_SpoolInfo]
						(
						Spool_oid
						) ON UPDATE  CASCADE 
						ON DELETE  CASCADE 
						) ON [PRIMARY]";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();

				sSql = @"create trigger SMgnt_PipeBend_trig_updateTime
						on [dbo].[SMgnt_PipeBend]
						after INSERT, UPDATE
						as
						begin
							declare @updateId bigint
							select @updateId=Id from inserted  
							update [dbo].[SMgnt_PipeBend] set [UpdateTime]=getdate() from [dbo].[SMgnt_PipeBend] where Id = @updateId
						end";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();
			}

			//PipeCheck
			sSql = $"select * from sysobjects where name='SMgnt_PipeCheck'";
			cmd = new SqlCommand(sSql, conn);
			if (cmd.ExecuteScalar() == null)
			{
				sSql = @"CREATE TABLE [dbo].[SMgnt_PipeCheck](
							Id bigint NOT NULL IDENTITY (1, 1),
							Spool_oid nvarchar(50) NOT NULL,
							Spool nvarchar(50) NOT NULL,
							Part_oid nvarchar(50) NOT NULL,
							Tag nvarchar(50) DEFAULT(''),
							OrderedLens nvarchar(200) DEFAULT(''),
							SaddleCut nvarchar(100) DEFAULT(''),
							MiterCut nvarchar(100) DEFAULT(''),
							CreateTime datetime DEFAULT CURRENT_TIMESTAMP,
							UpdateTime datetime DEFAULT CURRENT_TIMESTAMP
						CONSTRAINT [PK_SMgnt_PipeCheck] PRIMARY KEY CLUSTERED 
							(
							Id
							) WITH(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
						CONSTRAINT [FK_SMgnt_PipeCheck_SMgnt_SpoolInfo] FOREIGN KEY
							(
							[Spool_oid]
							) REFERENCES [dbo].[SMgnt_SpoolInfo] 
							(
							Spool_oid
							) ON UPDATE  CASCADE 
							ON DELETE  CASCADE,
						) ON [PRIMARY]";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();

				sSql = @"create trigger SMgnt_PipeCheck_trig_updateTime
						on [dbo].[SMgnt_PipeCheck]
						after INSERT, UPDATE
						as
						begin
							declare @updateId bigint
							select @updateId=Id from inserted  
							update [dbo].[SMgnt_PipeCheck] set [UpdateTime]=getdate() from [dbo].[SMgnt_PipeCheck] where Id = @updateId
						end";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();

			}

			//Assembly
			sSql = $"select * from sysobjects where name='SMgnt_PipeAssembly'";
			cmd = new SqlCommand(sSql, conn);
			if (cmd.ExecuteScalar() == null)
			{
				sSql = @"CREATE TABLE [dbo].[SMgnt_PipeAssembly](
							Id bigint NOT NULL IDENTITY (1, 1),
							Spool_oid nvarchar(50) NOT NULL,
							Spool nvarchar(50) NOT NULL,
							Part_oid nvarchar(50) NOT NULL,
							Tag nvarchar(50) DEFAULT(''),
							FlangeTurnAngle nvarchar(50) DEFAULT(''),
							BranchTurnAngle nvarchar(50) DEFAULT(''),
							BranchAngle nvarchar(50) DEFAULT(''),
							RefPartTag nvarchar(50) DEFAULT(''),
							RefPartOid nvarchar(50) DEFAULT(''),
							CreateTime datetime DEFAULT CURRENT_TIMESTAMP,
							UpdateTime datetime DEFAULT CURRENT_TIMESTAMP
						CONSTRAINT [PK_SMgnt_PipeAssembly] PRIMARY KEY CLUSTERED 
							(
							Id
							) WITH(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
						CONSTRAINT [FK_SMgnt_PipeAssembly_SMgnt_SpoolInfo] FOREIGN KEY
							(
							[Spool_oid]
							) REFERENCES [dbo].[SMgnt_SpoolInfo]
							(
							Spool_oid
							) ON UPDATE  CASCADE 
							ON DELETE  CASCADE 
						) ON [PRIMARY]";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();

				sSql = @"create trigger SMgnt_PipeAssembly_trig_updateTime
						on [dbo].[SMgnt_PipeAssembly]
						after INSERT, UPDATE
						as
						begin
							declare @updateId bigint
							select @updateId=Id from inserted  
							update [dbo].[SMgnt_PipeAssembly] set [UpdateTime]=getdate() from [dbo].[SMgnt_PipeAssembly] where Id = @updateId
						end";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();
			}

			//Issue
			sSql = $"select * from sysobjects where name='SMgnt_PipeIssue'";
			cmd = new SqlCommand(sSql, conn);
			if (cmd.ExecuteScalar() == null)
			{
				sSql = @"CREATE TABLE [dbo].[SMgnt_PipeIssue](
							Id bigint NOT NULL IDENTITY (1, 1),
							Spool_oid nvarchar(50) NOT NULL,
							Spool nvarchar(50) NOT NULL,
							Part nvarchar(50) NOT NULL,
							Issue nvarchar(1000) DEFAULT(''),
							RelatedTable nvarchar(50) NOT NULL,
							Level nvarchar(50) NOT NULL,
							CreateTime datetime DEFAULT CURRENT_TIMESTAMP,
							UpdateTime datetime DEFAULT CURRENT_TIMESTAMP
						CONSTRAINT [PK_SMgnt_PipeIssue] PRIMARY KEY CLUSTERED 
							(
							Id
							) WITH(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
						CONSTRAINT [FK_SMgnt_PipeIssue_SMgnt_SpoolInfo] FOREIGN KEY
							(
							[Spool_oid]
							) REFERENCES [dbo].[SMgnt_SpoolInfo]
							(
							Spool_oid
							) ON UPDATE  CASCADE 
							ON DELETE  CASCADE 
						) ON [PRIMARY]";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();

				sSql = @"create trigger SMgnt_PipeIssue_trig_updateTime
						on [dbo].[SMgnt_PipeIssue]
						after INSERT, UPDATE
						as
						begin
							declare @updateId bigint
							select @updateId=Id from inserted  
							update [dbo].[SMgnt_PipeIssue] set [UpdateTime]=getdate() from [dbo].[SMgnt_PipeIssue] where Id = @updateId
						end";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();
			}

			//History
			//SpoolInfo
			sSql = $"select * from sysobjects where name='SMgnt_History'";
			cmd = new SqlCommand(sSql, conn);
			if (cmd.ExecuteScalar() == null)
			{
				sSql = @"create table [dbo].[SMgnt_History](
							Id bigint NOT NULL IDENTITY (1, 1),
							Spool nvarchar(50) NOT NULL,
							Spool_oid nvarchar(50) NOT NULL,
							CreateBy nvarchar(50) NOT NULL,
							DeleteBy nvarchar(50) NOT NULL,
							CreateTime datetime DEFAULT CURRENT_TIMESTAMP,
							DeleteTime datetime DEFAULT CURRENT_TIMESTAMP
						CONSTRAINT [PK_SMgnt_History] PRIMARY KEY CLUSTERED 
							(
							Id
							) WITH(PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
						) ON [PRIMARY]";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();

				sSql = @"create trigger SMgnt_History_trig_updateTime
						on [dbo].[SMgnt_History]
						after INSERT, UPDATE
						as
						begin
							declare @updateId nvarchar(50)
							select @updateId=Id from inserted  
							update [dbo].[SMgnt_History] set [UpdateTime]=getdate() from [dbo].[SMgnt_History] where Id = @updateId
						end";
				cmd = new SqlCommand(sSql, conn);
				cmd.ExecuteNonQuery();
			}
		}

		/// <summary>
		/// 比较两个SMgntSpool是否一致（属性）
		/// </summary>
		/// <param name="oSpool1"></param>
		/// <param name="oSpool2"></param>
		/// <returns></returns>
		internal static bool IsSMgntSpoolSameAttr(SMgnt_SpoolInfo oSpool1, SMgnt_SpoolInfo oSpool2)
		{
			//if (oSpool1.CalculateCode != oSpool2.CalculateCode)
			//	return false;
			if (Convert.ToDouble(oSpool1.Weight - oSpool2.Weight) > 0.01)
				return false;
			if (oSpool1.Type != oSpool2.Type)
				return false;
			if (oSpool1.GroupType != oSpool2.GroupType)
				return false;
			if (oSpool1.SpecName != oSpool2.SpecName)
				return false;
			if (oSpool1.TestPressure != oSpool2.TestPressure)
				return false;
			if (oSpool1.InnerTreatment != oSpool2.InnerTreatment)
				return false;
			if (oSpool1.OutterTreatment != oSpool2.OutterTreatment)
				return false;
			//if (oSpool1.StringAssemblyInfo != oSpool2.StringAssemblyInfo)
			//	return false;
			//if (oSpool1.StringPipeBendInfo != oSpool2.StringPipeBendInfo)
			//	return false;
			//if (oSpool1.StringPipeCheckInfo != oSpool2.StringPipeCheckInfo)
			//	return false;
			//if (oSpool1.StringPipePartInfo != oSpool2.StringPipePartInfo)
			//	return false;
			//if (oSpool1.StringPipeSpoolInfo != oSpool2.StringPipeSpoolInfo)
			//	return false;
			//if (oSpool1.StringPipeWeldInfo != oSpool2.StringPipeWeldInfo)
			//	return false;
			//if (oSpool1.StringStartEndInfo != oSpool2.StringStartEndInfo)
			//	return false;

			return true;
		}

		internal static bool IsSMgntSpoolSameShape(SMgnt_SpoolInfo oSpool1, SMgnt_SpoolInfo oSpool2)
		{
			if (oSpool1.CalculateCode != oSpool2.CalculateCode)
				return false;
			//if (Convert.ToDouble(oSpool1.Weight - oSpool2.Weight) > 0.01)
			//	return false;
			//if (oSpool1.Type != oSpool2.Type)
			//	return false;
			//if (oSpool1.GroupType != oSpool2.GroupType)
			//	return false;
			//if (oSpool1.SpecName != oSpool2.SpecName)
			//	return false;
			//if (oSpool1.TestPressure != oSpool2.TestPressure)
			//	return false;
			//if (oSpool1.InnerTreatment != oSpool2.InnerTreatment)
			//	return false;
			//if (oSpool1.OutterTreatment != oSpool2.OutterTreatment)
			//	return false;
			//if (oSpool1.StringAssemblyInfo != oSpool2.StringAssemblyInfo)
			//	return false;
			//if (oSpool1.StringPipeBendInfo != oSpool2.StringPipeBendInfo)
			//	return false;
			//if (oSpool1.StringPipeCheckInfo != oSpool2.StringPipeCheckInfo)
			//	return false;
			//if (oSpool1.StringPipePartInfo != oSpool2.StringPipePartInfo)
			//	return false;
			//if (oSpool1.StringPipeSpoolInfo != oSpool2.StringPipeSpoolInfo)
			//	return false;
			//if (oSpool1.StringPipeWeldInfo != oSpool2.StringPipeWeldInfo)
			//	return false;
			//if (oSpool1.StringStartEndInfo != oSpool2.StringStartEndInfo)
			//	return false;

			return true;
		}
		/// <summary>
		/// 比较两根小票间是否节点一致
		/// </summary>
		/// <param name="oSpool1"></param>
		/// <param name="oSpool2"></param>
		/// <returns></returns>
		internal static bool IsSMgntSpoolSameNode(SMgnt_SpoolInfo oSpool1, SMgnt_SpoolInfo oSpool2)
		{
			return oSpool1.ParentAss == oSpool2.ParentAss && oSpool1.Zone == oSpool2.Zone && oSpool1.Block == oSpool2.Block && oSpool1.Major == oSpool2.Major;
		}

		/// <summary>
		/// 比较两根小票间是否名称一致
		/// </summary>
		/// <param name="oSpool1"></param>
		/// <param name="oSpool2"></param>
		/// <returns></returns>
		internal static bool IsSMgntSpoolSameName(SMgnt_SpoolInfo oSpool1, SMgnt_SpoolInfo oSpool2)
		{
			return oSpool1.Name == oSpool2.Name;
		}


		/// <summary>
		/// 获取PipeSpool所在的分区与分段
		/// </summary>
		/// <param name="oBOOnSpool"></param>
		/// <param name="sArea"></param>
		/// <param name="sBlock"></param>
		public static void GetSpoolAreaAndBlock(BusinessObject oBOOnSpool, ref string sArea, ref ParentAss oBlock)
		{
			BusinessObject oParent = GetAssemblyParent(oBOOnSpool, 2);
			if (oParent != null)
			{
				oBlock.Name = oParent.ToString();
				oBlock.OID = oParent.ObjectID;
			}

			oParent = GetAssemblyParent(oBOOnSpool, 3);
			if (oParent != null)
			{
				sArea = oParent.ToString();
			}
		}

		/// <summary>
		/// 获取装配对象的父级
		/// </summary>
		/// <param name="iObject"></param>
		/// <param name="iUpLever"></param>
		/// <returns></returns>
		public static BusinessObject GetAssemblyParent(BusinessObject iObject, int iUpLever)
		{
			BusinessObject oParent = null;
			if (iUpLever == 0)
				oParent = iObject;
			else
			{
				var childAssembly = iObject as IAssemblyChild;
				BusinessObject otempParent = null;
				if (childAssembly != null && (otempParent = childAssembly.AssemblyParent as BusinessObject) != null)
					oParent = GetAssemblyParent(otempParent, --iUpLever);
				else
					oParent = iObject;
			}

			return oParent;
		}

		/// <summary>
		/// 将Spool信息转换为数据库实例对象
		/// </summary>
		/// <param name="oTMSpool"></param>
		/// <returns></returns>
		public static SMgnt_SpoolInfo ConvertTMSpoolToDBSpoolInfo(TMSpool oTMSpool)
		{
			string sCurrUser = ProjectMgmtHelper.GetCurrentAccountUserName(true);

			SMgnt_SpoolInfo oPIPSpoolInfo = new SMgnt_SpoolInfo();
			oPIPSpoolInfo.Spool_oid = oTMSpool.OID;
			oPIPSpoolInfo.CalculateCode = oTMSpool.VerifyCodeForPhysical;
			oPIPSpoolInfo.Zone = oTMSpool.ZoneOrAreaName;
			oPIPSpoolInfo.Block = oTMSpool.BlockName;
			oPIPSpoolInfo.Name = oTMSpool.Name;
			oPIPSpoolInfo.Spool = oPIPSpoolInfo.Zone + "-" + oPIPSpoolInfo.Block + "-" + oPIPSpoolInfo.Name;
			oPIPSpoolInfo.Block_oid = oTMSpool.BlockOid;
			oPIPSpoolInfo.Weight = Convert.ToDecimal(oTMSpool.Weight);
			oPIPSpoolInfo.Type = oTMSpool.Type;
			oPIPSpoolInfo.GroupType = oTMSpool.PipeGroup;
			oPIPSpoolInfo.SpecName = oTMSpool.PipeSpec;
			oPIPSpoolInfo.TestPressure = oTMSpool.TestPressure;
			oPIPSpoolInfo.InnerTreatment = oTMSpool.InnerSurfaceTreatment;
			oPIPSpoolInfo.OutterTreatment = oTMSpool.OuterSurfaceTreatment;
			oPIPSpoolInfo.CreateBy = sCurrUser;
			oPIPSpoolInfo.StartInfo = oTMSpool.StartInfo.ToString();
			oPIPSpoolInfo.EndInfo = oTMSpool.EndInfo.ToString();
			oPIPSpoolInfo.StringAssemblyInfo = oTMSpool.StringAssemblyInfo;
			oPIPSpoolInfo.StringPipeBendInfo = oTMSpool.StringPipeBendInfo;
			oPIPSpoolInfo.StringPipeCheckInfo = oTMSpool.StringPipeCheckInfo;
			oPIPSpoolInfo.StringPipePartInfo = oTMSpool.StringPipePartInfo;
			oPIPSpoolInfo.StringPipeSpoolInfo = oTMSpool.StringPipeSpoolInfo;
			oPIPSpoolInfo.StringPipeWeldInfo = oTMSpool.StringPipeWeldInfo;
			oPIPSpoolInfo.StringStartEndInfo = oTMSpool.StringStartEndInfo;

			oPIPSpoolInfo.PlusInnerSurfaceArea = (decimal)oTMSpool.PlusInnerSurfaceArea;
			if (oTMSpool.PlusIsSRTP)
				oPIPSpoolInfo.PlusIsSRTP = 1;
			else
				oPIPSpoolInfo.PlusIsSRTP = 0;
			oPIPSpoolInfo.PlusOuterSurfaceArea = (decimal)oTMSpool.PlusOuterSurfaceArea;
			oPIPSpoolInfo.PlusProductionLine = oTMSpool.PlusProductionLine;
			oPIPSpoolInfo.PlusSpoolClass = oTMSpool.PlusSpoolClass;
			oPIPSpoolInfo.PlusSpoolDescription = oTMSpool.PlusSpoolDescription;
			oPIPSpoolInfo.PlusSpoolLength = (decimal)oTMSpool.PlusSpoolLength;
			oPIPSpoolInfo.PlusSpoolMaterialGrade = oTMSpool.PlusSpoolMaterialGrade;
			oPIPSpoolInfo.PlusSpoolNPD = (decimal)oTMSpool.PlusSpoolNPD;
			oPIPSpoolInfo.PlusSpoolPOD = (decimal)oTMSpool.PlusSpoolPOD;
			oPIPSpoolInfo.PlusSpoolWallThickness = (decimal)oTMSpool.PlusSpoolWallThickness;
			oPIPSpoolInfo.PlusWBS = oTMSpool.PlusWBS;

			//构造PipePart实例对象
			if (oTMSpool.PipePartInfo != null)
			{
				SMgnt_PipePart oPIPPart = null;
				foreach (DataRow row in oTMSpool.PipePartInfo.Rows)
				{
					oPIPPart = new SMgnt_PipePart();
					oPIPPart.Spool = oPIPSpoolInfo.Spool;
					oPIPPart.Part_oid = row[PipePartTable.Part_oid].ToString();
					oPIPPart.Tag = row[PipePartTable.Tag].ToString();
					oPIPPart.MatCode = row[PipePartTable.MatCode].ToString();
					oPIPPart.MatDesc = row[PipePartTable.MatDesc].ToString();
					oPIPPart.EndCut = row[PipePartTable.EndCut].ToString();
					oPIPPart.Qty = Convert.ToDecimal(row[PipePartTable.Qty]);
					oPIPPart.BendPlus = Convert.ToDecimal(row[PipePartTable.BendPlus]);
					oPIPPart.QtyDesc = row[PipePartTable.QtyDesc].ToString();
					oPIPPart.ModelLen = Convert.ToDecimal(row[PipePartTable.ModelLen]);
					oPIPPart.Weight = Convert.ToDecimal(row[PipePartTable.Weight]);
					oPIPPart.Priority = row[PipePartTable.Priority].ToString();
					oPIPPart.Class = (int)row[PipePartTable.Class];
					oPIPPart.GeometryStd = row[PipePartTable.GeometryStd].ToString();

					oPIPSpoolInfo.SMgnt_PipePart.Add(oPIPPart);
				}
			}

			//构造PipeWeld实例对象
			if (oTMSpool.PipeWeldInfo != null)
			{
				SMgnt_PipeWeld oPIPWeld = null;
				foreach (DataRow row in oTMSpool.PipeWeldInfo.Rows)
				{
					oPIPWeld = new SMgnt_PipeWeld();
					oPIPWeld.Spool = oPIPSpoolInfo.Spool;
					oPIPWeld.Weld_oid = row[PipeWeldTable.Weld_oid].ToString();
					oPIPWeld.Tag = row[PipeWeldTable.Tag].ToString();
					oPIPWeld.Type = row[PipeWeldTable.Type].ToString();
					oPIPWeld.Code = row[PipeWeldTable.Code].ToString();
					oPIPWeld.Size = row[PipeWeldTable.Size].ToString();
					oPIPWeld.Thickness = row[PipeWeldTable.Thickness].ToString();
					oPIPWeld.Conn = row[PipeWeldTable.Conn].ToString();
					oPIPWeld.ConnDesc = row[PipeWeldTable.ConnDesc].ToString();
					oPIPWeld.PipeGrade = row[PipeWeldTable.PipeGrade].ToString();
					oPIPWeld.Stage = row[PipeWeldTable.Stage].ToString();

					oPIPSpoolInfo.SMgnt_PipeWeld.Add(oPIPWeld);
				}
			}

			//构造PipeBend实例对象
			if (oTMSpool.PipeBendInfo != null)
			{
				SMgnt_PipeBend oPIPBend = null;
				foreach (DataRow row in oTMSpool.PipeBendInfo.Rows)
				{
					oPIPBend = new SMgnt_PipeBend();
					oPIPBend.Spool = oPIPSpoolInfo.Spool;
					oPIPBend.TurnFeature_oid = row[PipeBendTable.TurnFeature_oid].ToString();
					oPIPBend.Part_oid = row[PipeBendTable.Part_oid].ToString();
					oPIPBend.Tag = row[PipeBendTable.Tag].ToString();
					oPIPBend.PullLen = row[PipeBendTable.PullLen].ToString();
					oPIPBend.BendRadius = row[PipeBendTable.BendRadius].ToString();
					oPIPBend.BendAngle = row[PipeBendTable.BendAgnle].ToString();
					oPIPBend.TurnAngle = row[PipeBendTable.TurnAngle].ToString();
					oPIPBend.CutLen = row[PipeBendTable.CutLen].ToString();
					oPIPBend.TailCutLen = row[PipeBendTable.TailCutLen].ToString();
					oPIPBend.BendStartLen = row[PipeBendTable.BendStartLen].ToString();

					oPIPSpoolInfo.SMgnt_PipeBend.Add(oPIPBend);
				}
			}

			//构造PipeCheck实例对象
			if (oTMSpool.PipeCheckInfo != null)
			{
				SMgnt_PipeCheck oPIPCheck = null;
				foreach (DataRow row in oTMSpool.PipeCheckInfo.Rows)
				{
					oPIPCheck = new SMgnt_PipeCheck();
					oPIPCheck.Spool = oPIPSpoolInfo.Spool;
					oPIPCheck.Part_oid = row[PipeCheckTable.Part_oid].ToString();
					oPIPCheck.Tag = row[PipeCheckTable.Tag].ToString();
					oPIPCheck.OrderedLens = row[PipeCheckTable.OrderedLens].ToString();
					oPIPCheck.SaddleCut = row[PipeCheckTable.SaddleCut].ToString();
					oPIPCheck.MiterCut = row[PipeCheckTable.MiterCut].ToString();

					oPIPSpoolInfo.SMgnt_PipeCheck.Add(oPIPCheck);
				}
			}

			//构造PipeAssembly实例对象
			if (oTMSpool.AssemblyInfo != null)
			{
				SMgnt_PipeAssembly oPIPAssembly = null;
				foreach (DataRow row in oTMSpool.AssemblyInfo.Rows)
				{
					oPIPAssembly = new SMgnt_PipeAssembly();
					oPIPAssembly.Spool = oPIPSpoolInfo.Spool;
					oPIPAssembly.Part_oid = row[PipeAssemblyTable.Part_oid].ToString();
					oPIPAssembly.Tag = row[PipeAssemblyTable.Tag].ToString();
					oPIPAssembly.FlangeTurnAngle = row[PipeAssemblyTable.FlangeTurnAngle].ToString();
					oPIPAssembly.BranchTurnAngle = row[PipeAssemblyTable.BranchTurnAngle].ToString();
					oPIPAssembly.BranchAngle = row[PipeAssemblyTable.BranchAngle].ToString();
					oPIPAssembly.RefPartTag = row[PipeAssemblyTable.RefPartTag].ToString();
					oPIPAssembly.RefPartOid = row[PipeAssemblyTable.RefPartOid].ToString();

					oPIPSpoolInfo.SMgnt_PipeAssembly.Add(oPIPAssembly);
				}
			}

			//构造PipeIssue实例对象
			if (oTMSpool.IssueInfo != null)
			{
				SMgnt_PipeIssue oPIPIssue = null;
				foreach (DataRow row in oTMSpool.IssueInfo.Rows)
				{
					oPIPIssue = new SMgnt_PipeIssue();
					oPIPIssue.Spool = oPIPSpoolInfo.Spool;
					oPIPIssue.Part = row[PipeIssueTable.Part].ToString();
					oPIPIssue.Issue = row[PipeIssueTable.Issue].ToString();
					oPIPIssue.RelatedTable = row[PipeIssueTable.RelatedTable].ToString();
					oPIPIssue.Level = row[PipeIssueTable.Lever].ToString();

					oPIPSpoolInfo.SMgnt_PipeIssue.Add(oPIPIssue);
				}
			}

			return oPIPSpoolInfo;
		}

		/// <summary>
		/// 属性拷贝
		/// </summary>
		/// <param name="oSpool"></param>
		/// <param name="oSpoolCopyFrom"></param>
		public static void CopyAttr(ref SMgnt_SpoolInfo oSpool, SMgnt_SpoolInfo oSpoolCopyFrom)
		{
			oSpool.CalculateCode = oSpoolCopyFrom.CalculateCode;
			oSpool.Zone = oSpoolCopyFrom.Zone;
			oSpool.Block = oSpoolCopyFrom.Block;
			oSpool.Name = oSpoolCopyFrom.Name;
			oSpool.Spool = oSpoolCopyFrom.Spool;
			oSpool.Block_oid = oSpoolCopyFrom.Block_oid;
			oSpool.ParentAss = oSpoolCopyFrom.ParentAss;
			oSpool.ParentAss_oid = oSpoolCopyFrom.ParentAss_oid;
			oSpool.Weight = oSpoolCopyFrom.Weight;
			oSpool.Type = oSpoolCopyFrom.Type;
			oSpool.GroupType = oSpoolCopyFrom.GroupType;
			oSpool.SpecName = oSpoolCopyFrom.SpecName;
			oSpool.TestPressure = oSpoolCopyFrom.TestPressure;
			oSpool.InnerTreatment = oSpoolCopyFrom.InnerTreatment;
			oSpool.OutterTreatment = oSpoolCopyFrom.OutterTreatment;
			oSpool.CreateBy = oSpoolCopyFrom.CreateBy;
			oSpool.StartInfo = oSpoolCopyFrom.StartInfo;
			oSpool.EndInfo = oSpoolCopyFrom.EndInfo;
			oSpool.StringAssemblyInfo = oSpoolCopyFrom.StringAssemblyInfo;
			oSpool.StringPipeBendInfo = oSpoolCopyFrom.StringPipeBendInfo;
			oSpool.StringPipeCheckInfo = oSpoolCopyFrom.StringPipeCheckInfo;
			oSpool.StringPipePartInfo = oSpoolCopyFrom.StringPipePartInfo;
			oSpool.StringPipeSpoolInfo = oSpoolCopyFrom.StringPipeSpoolInfo;
			oSpool.StringPipeWeldInfo = oSpoolCopyFrom.StringPipeWeldInfo;
			oSpool.StringStartEndInfo = oSpoolCopyFrom.StringStartEndInfo;
			oSpool.PlusInnerSurfaceArea = oSpoolCopyFrom.PlusInnerSurfaceArea;
			oSpool.PlusIsSRTP = oSpoolCopyFrom.PlusIsSRTP;
			oSpool.PlusOuterSurfaceArea = oSpoolCopyFrom.PlusOuterSurfaceArea;
			oSpool.PlusProductionLine = oSpoolCopyFrom.PlusProductionLine;
			oSpool.PlusSpoolClass = oSpoolCopyFrom.PlusSpoolClass;
			oSpool.PlusSpoolDescription = oSpoolCopyFrom.PlusSpoolDescription;
			oSpool.PlusSpoolLength = oSpoolCopyFrom.PlusSpoolLength;
			oSpool.PlusSpoolMaterialGrade = oSpoolCopyFrom.PlusSpoolMaterialGrade;
			oSpool.PlusSpoolNPD = oSpoolCopyFrom.PlusSpoolNPD;
			oSpool.PlusSpoolPOD = oSpoolCopyFrom.PlusSpoolPOD;
			oSpool.PlusSpoolWallThickness = oSpoolCopyFrom.PlusSpoolWallThickness;
			oSpool.PlusWBS = oSpoolCopyFrom.PlusWBS;
			oSpool.PipeLineSystemPath = oSpoolCopyFrom.PipeLineSystemPath;
			oSpool.IsBendPipe = oSpoolCopyFrom.IsBendPipe;
			oSpool.Major = oSpoolCopyFrom.Major;
			oSpool.ModificationFileCode = oSpoolCopyFrom.ModificationFileCode;
			oSpool.SpoolPath = oSpoolCopyFrom.SpoolPath;
		}

		/// <summary>
		/// 将模型Spool列表对象构建为SMgntSpool列表对象
		/// </summary>
		/// <param name="oSpools"></param>
		/// <returns></returns>
		public static List<SMgnt_SpoolInfo> BuildSMgntSpoolList(List<BusinessObject> oSpools, ref Dictionary<string, SMgnt_SpoolInfo> oSMgntSpoolCache, System.Windows.Forms.ToolStripStatusLabel infoLabel = null, bool bUseCache = false)
		{
			List<SMgnt_SpoolInfo> oSMgntSpools = new List<SMgnt_SpoolInfo>();

			foreach (var spool in oSpools)
			{
				if (infoLabel != null)
					infoLabel.Text = $"正在构建小票{spool.ToString()}的信息...";

				oSMgntSpools.Add(BuildSMgntSpool(spool, ref oSMgntSpoolCache, bUseCache));
			}

			return oSMgntSpools;
		}

		/// <summary>
		/// 将模型Spool对象构建为SMgntSpool
		/// </summary>
		/// <param name="oBOOnSpool"></param>
		/// <returns></returns>
		public static SMgnt_SpoolInfo BuildSMgntSpool(BusinessObject oBOOnSpool, ref Dictionary<string, SMgnt_SpoolInfo> oSMgntSpoolCache, bool bUseCache = false)
		{
			//从缓存中查找
			if (bUseCache && oSMgntSpoolCache.ContainsKey(oBOOnSpool.ObjectID))
				return oSMgntSpoolCache[oBOOnSpool.ObjectID];

			//从模型构建
			SMgnt_SpoolInfo oSMgntSpool = null;
			TMSpool oTMSpool = null;
			try
			{
				oTMSpool = new TMSpool(oBOOnSpool);
				oTMSpool.AchieveData();

				oSMgntSpool = CommonFunctions.ConvertTMSpoolToDBSpoolInfo(oTMSpool);
				oSMgntSpool.SpoolFromModel = oBOOnSpool;

				//材料节点信息
				BusinessObject oMatBO = GetMatFromSpool(oBOOnSpool);
				if (oMatBO == null)
				{
					oSMgntSpool.ParentAss = "Undefined";
					oSMgntSpool.ParentAss_oid = "Undefined";
				}
				else
				{
					oSMgntSpool.ParentAss = oMatBO.ToString();
					oSMgntSpool.ParentAss_oid = oMatBO.ObjectID;
				}

				//系统路径
				oSMgntSpool.PipeLineSystemPath = GetSystemPathFromSpool(oBOOnSpool);

				//装配路径
				oSMgntSpool.SpoolPath = GetSpoolPathFromSpool(oBOOnSpool);

				//专业
				oSMgntSpool.Major = GetMajor(oBOOnSpool);

				//是否为弯管
				if (oSMgntSpool.SMgnt_PipeBend.Count != 0)
					oSMgntSpool.IsBendPipe = 1;
				else
					oSMgntSpool.IsBendPipe = 0;
			}
			catch
			{
				oSMgntSpool = BuildSimpleSMgntSpool(oBOOnSpool);
				oSMgntSpool.RowStatus = (int)RowStatus.ERROR;
			}

			//存储到缓存
			oSMgntSpoolCache[oSMgntSpool.Spool_oid] = oSMgntSpool;

			return oSMgntSpool;
		}

		/// <summary>
		/// 构建一个简单数据库小票信息
		/// </summary>
		/// <param name="oSpoolBO"></param>
		/// <returns></returns>
		public static SMgnt_SpoolInfo BuildSimpleSMgntSpool(BusinessObject oSpoolBO)
		{
			SMgnt_SpoolInfo oSMgntSpool = new SMgnt_SpoolInfo();

			oSMgntSpool.Spool_oid = oSpoolBO.ObjectID;

			oSMgntSpool.CalculateCode = oSpoolBO.ObjectID;

			oSMgntSpool.Name = oSpoolBO.ToString();

			oSMgntSpool.Major = GetMajor(oSpoolBO);

			//材料节点信息
			BusinessObject oMatBO = GetMatFromSpool(oSpoolBO);
			if (oMatBO == null)
			{
				oSMgntSpool.ParentAss = "Undefined";
				oSMgntSpool.ParentAss_oid = "Undefined";
			}
			else
			{
				oSMgntSpool.ParentAss = oMatBO.ToString();
				oSMgntSpool.ParentAss_oid = oMatBO.ObjectID;
			}

			//分段信息
			BusinessObject oBloclBO = GetBlockFromSpool(oSpoolBO);
			if (oBloclBO == null)
			{
				oSMgntSpool.Block = "Undefined";
				oSMgntSpool.Block_oid = "Undefined";
			}
			else
			{
				oSMgntSpool.Block = oBloclBO.ToString();
				oSMgntSpool.Block_oid = oBloclBO.ObjectID;
			}

			//分区信息
			BusinessObject oZoneBO = GetZoneFromSpool(oSpoolBO);
			if (oZoneBO == null)
			{
				oSMgntSpool.Zone = "Undefined";
			}
			else
			{
				oSMgntSpool.Zone = oZoneBO.ToString();
			}

			//有效性
			oSMgntSpool.IsValid = 0;

			//系统路径
			oSMgntSpool.PipeLineSystemPath = GetSystemPathFromSpool(oSpoolBO);

			//装配路径
			oSMgntSpool.SpoolPath = GetSpoolPathFromSpool(oSpoolBO);

			return oSMgntSpool;
		}

		public static BusinessObject GetMatFromSpool(BusinessObject oSpool)
		{
			IAssemblyChild oAssChildOnSpool = oSpool as IAssemblyChild;
			if (oAssChildOnSpool == null)
				return null;

			return oAssChildOnSpool.AssemblyParent as BusinessObject;
		}

		public static BusinessObject GetBlockFromSpool(BusinessObject oSpool)
		{
			BusinessObject oMat = GetMatFromSpool(oSpool);
			if (oMat == null)
				return null;

			IAssemblyChild oAssChild = oMat as IAssemblyChild;
			if (oAssChild == null)
				return null;

			return oAssChild.AssemblyParent as BusinessObject;
		}

		public static BusinessObject GetZoneFromSpool(BusinessObject oSpool)
		{
			BusinessObject oBlock = GetBlockFromSpool(oSpool);
			if (oBlock == null)
				return null;

			IAssemblyChild oAssParent = oBlock as IAssemblyChild;
			if (oAssParent == null)
				return null;

			return oAssParent.AssemblyParent as BusinessObject;
		}


		public static string GetSpoolPathFromSpool(BusinessObject oSpool)
		{
			string sPath = "";

			return GetSpoolPath(sPath, oSpool);
		}

		public static string GetSpoolPath(string sChildPath, BusinessObject oBo)
		{
			string sPath = oBo.ToString() + "\\" + sChildPath;

			IAssemblyChild oAssemblyChild = oBo as IAssemblyChild;
			if (oAssemblyChild != null && oAssemblyChild.AssemblyParent != null)
			{
				sPath = GetSpoolPath(sPath, oAssemblyChild.AssemblyParent as BusinessObject);
			}

			return sPath;
		}

		/// <summary>
		/// 从数据库获取已有的分区和分段信息
		/// </summary>
		/// <param name="oEntities"></param>
		/// <returns></returns>
		public static Dictionary<string, Dictionary<string, Dictionary<string, List<ParentAss>>>> GetAreaBlockAndParentAssMapFromDB(SMgntEntities oEntities)
		{
			Dictionary<string, Dictionary<string, Dictionary<string, List<ParentAss>>>> majorMap = new Dictionary<string, Dictionary<string, Dictionary<string, List<ParentAss>>>>();
			Dictionary<string, Dictionary<string, List<ParentAss>>> areaMap = null;
			Dictionary<string, List<ParentAss>> blockMap = null;
			List<ParentAss> currentParentAssList = null;
			foreach (SMgnt_SpoolInfo spool in oEntities.SMgnt_SpoolInfo)
			{
				if (majorMap.ContainsKey(spool.Major))
				{
					areaMap = majorMap[spool.Major];
				}
				else
				{
					areaMap = new Dictionary<string, Dictionary<string, List<ParentAss>>>();
					majorMap[spool.Major] = areaMap;
				}

				if (areaMap.ContainsKey(spool.Zone))
				{
					blockMap = areaMap[spool.Zone];
				}
				else
				{
					blockMap = new Dictionary<string, List<ParentAss>>();
					areaMap[spool.Zone] = blockMap;
				}

				if (blockMap.ContainsKey(spool.Block))
				{
					currentParentAssList = blockMap[spool.Block];
				}
				else
				{
					currentParentAssList = new List<ParentAss>();
					blockMap[spool.Block] = currentParentAssList;
				}

				ParentAss currParentAss = new ParentAss();
				currParentAss.Name = spool.ParentAss;
				currParentAss.OID = spool.ParentAss_oid;
				if (!currentParentAssList.Contains(currParentAss))
				{
					currentParentAssList.Add(currParentAss);
				}
			}

			return majorMap;
		}

		/// <summary>
		/// 从SMgntSpool列表中，找到指定名称的小票。未找到返回null
		/// </summary>
		/// <param name="sFullName">Area+Block+Name</param>
		/// <param name="listSMgntSpools"></param>
		/// <returns></returns>
		public static SMgnt_SpoolInfo FindSMgntSpoolByFullName(string sFullName, List<SMgnt_SpoolInfo> listSMgntSpools)
		{
			SMgnt_SpoolInfo oSMgntSpool = null;
			foreach (var it in listSMgntSpools)
			{
				if (it.Spool == sFullName)
				{
					oSMgntSpool = it;
					break;
				}
			}
			return oSMgntSpool;
		}

		/// <summary>
		/// 通过区域，分段，小票id查找Spool
		/// </summary>
		/// <param name="sZone"></param>
		/// <param name="sBlock"></param>
		/// <param name="sOID"></param>
		/// <param name="listSMgntSpools"></param>
		/// <returns></returns>
		public static SMgnt_SpoolInfo FindSMgntSpoolByZoneBlockAndOID(string sMajor, string sZone, string sBlock, string sOID, List<SMgnt_SpoolInfo> listSMgntSpools)
		{
			foreach (var it in listSMgntSpools)
			{
				if (it.Major == sMajor && it.Zone == sZone && it.Block == sBlock && it.Spool_oid == sOID)
					return it;
			}

			return null;
		}

		/// <summary>
		/// 从列表中找到匹配的对象
		/// </summary>
		/// <param name="sKey"></param>
		/// <param name="oidAndSpoolMap"></param>
		/// <returns></returns>
		public static List<BusinessObject> FindObjcetByKey(string sKey, Dictionary<string, BusinessObject> oSpoolList)
		{
			List<BusinessObject> oObjects = new List<BusinessObject>();
			foreach (var it in oSpoolList)
			{
				if (it.Value.ToString() == sKey)
					oObjects.Add(it.Value);
			}

			return oObjects;
		}

		/// <summary>
		/// 通过物理唯一码获取小票对象
		/// </summary>
		/// <param name="sKey"></param>
		/// <param name="oSMgntSpools"></param>
		/// <param name="oSpools"></param>
		/// <returns></returns>
		public static BusinessObject FindSpoolByCalculateCode(string sKey, List<SMgnt_SpoolInfo> oSMgntSpools, List<BusinessObject> oSpools)
		{
			for (int i=0; i<oSMgntSpools.Count; i++)
			{
				if (oSMgntSpools[i].CalculateCode == sKey)
					return oSpools[i];
			}

			return null ;
		}

		/// <summary>
		/// 获取小票所在分区、分段和父级节点信息
		/// </summary>
		/// <param name="oSpool"></param>
		/// <param name="sArea"></param>
		/// <param name="sBlock"></param>
		/// <param name="parentAss"></param>
		public static bool GetAreaBloclAndParentAss(BusinessObject oSpool, ref string sMajor, ref string sArea, ref string sBlock, ref ParentAss parentAss)
		{
			IAssemblyChild oIAssemblyChild = oSpool as IAssemblyChild;
			if (oIAssemblyChild == null)
				return false;
			
			//父级
			Assembly oAssembly = oIAssemblyChild.AssemblyParent as Assembly;
			parentAss.Name = oAssembly.Name;
			parentAss.OID = oAssembly.ObjectID;

			//专业
			sMajor = GetMajor(oSpool);

			//分区、分段
			int iUpLevel = 0;
			while (oAssembly != null && ++iUpLevel < 5)
			{
				if (oAssembly.AssemblyType == 2 ||
					oAssembly.AssemblyType == 15 ||
					oAssembly.AssemblyType == 6)
				{
					sBlock = oAssembly.Name;

					//分段父级节点为分区
					oAssembly = oAssembly.AssemblyParent as Assembly;
					if (oAssembly == null)
						return false;

					sArea = oAssembly.Name;
					return true;
				}

				oAssembly = oAssembly.AssemblyParent as Assembly;
			}

			return false;
		}

		/// <summary>
		/// 获取专业信息
		/// </summary>
		/// <param name="oBo"></param>
		/// <returns></returns>
		public static string GetMajor(BusinessObject oBO)
		{
			string sSpoolPath = GetSpoolPathFromSpool(oBO);

			foreach(var it in ConfigManager.ConfigMap)
			{
				Regex reg = new Regex(it.Key);
				if (reg.Matches(sSpoolPath).Count != 0)
					return it.Value;
			}

			return "Undefined";
		}

		/// <summary>
		/// 对象居中
		/// </summary>
		/// <param name="oBO"></param>
		public static void FitObject(BusinessObject oBO)
		{
			ClientServiceProvider.SelectSet.SelectedObjects.Clear();
			ClientServiceProvider.SelectSet.SelectedObjects.Add(oBO);

			try
			{
				IRange oRange = oBO as IRange;
				if (oRange != null)
				{
					ClientServiceProvider.GraphicViewMgr.ActiveView.Camera.ZoomToWorldRange(oRange.Range.Low, oRange.Range.High);
				}
				else
				{
					double lowX = 0.0;
					double lowY = 0.0;
					double lowZ = 0.0;
					double hiX = 0.0;
					double hiY = 0.0;
					double hiZ = 0.0;
					IJDGraphicRange graphicRange = new CoGraphicEntityMgr() as IJDGraphicRange;
					graphicRange.GetGRangeForSelectedAspects(COMConverters.ConvertBOToCOMBO(oBO), ref lowX, ref lowY, ref lowZ, ref hiX, ref hiY, ref hiZ);
					Position lowPos = new Position(lowX, lowY, lowZ);
					Position hiPos = new Position(hiX, hiY, hiZ);

					ClientServiceProvider.GraphicViewMgr.ActiveView.Camera.ZoomToWorldRange(lowPos, hiPos);
				}
			}
			catch (Exception ex)
			{
				MessageBox.Show("无法获取当前对象空间范围，居中失败。");
			}
		}
		public static void FitObjects(List<BusinessObject> oBOs)
		{
			ClientServiceProvider.SelectSet.SelectedObjects.Clear();

			Position lowPos = null, highPos = null;
			foreach (var oBO in oBOs)
			{
				if (oBO == null)
					continue;

				ClientServiceProvider.SelectSet.SelectedObjects.Add(oBO);

				Position TemplowPos = null, TempHighPos = null;
				IRange oRange = oBO as IRange;
				if (oRange != null)
				{
					TemplowPos = oRange.Range.Low;
					TempHighPos = oRange.Range.High;
				}
				else
				{
					double lowX = 0.0;
					double lowY = 0.0;
					double lowZ = 0.0;
					double hiX = 0.0;
					double hiY = 0.0;
					double hiZ = 0.0;
					IJDGraphicRange graphicRange = new CoGraphicEntityMgr() as IJDGraphicRange;
					graphicRange.GetGRangeForSelectedAspects(COMConverters.ConvertBOToCOMBO(oBO), ref lowX, ref lowY, ref lowZ, ref hiX, ref hiY, ref hiZ);
					TemplowPos = new Position(lowX, lowY, lowZ);
					TempHighPos = new Position(hiX, hiY, hiZ);
				}

				//计算当前最高点最低点
				if (lowPos == null || highPos == null)
				{
					lowPos = TemplowPos;
					highPos = TempHighPos;
					continue;
				}

				if (lowPos.X > TemplowPos.X)
					lowPos.X = TemplowPos.X;
				if (lowPos.Y > TemplowPos.Y)
					lowPos.Y = TemplowPos.Y;
				if (lowPos.Z > TemplowPos.Z)
					lowPos.Z = TemplowPos.Z;

				if (highPos.X < TempHighPos.X)
					highPos.X = TempHighPos.X;
				if (highPos.Y < TempHighPos.Y)
					highPos.Y = TempHighPos.Y;
				if (highPos.Z < TempHighPos.Z)
					highPos.Z = TempHighPos.Z;
			}

			if (lowPos != null && highPos != null)
				ClientServiceProvider.GraphicViewMgr.ActiveView.Camera.ZoomToWorldRange(lowPos, highPos);
		}


		/// <summary>
		/// 判断列表中的小票是否位于同一个装配节点下
		/// </summary>
		/// <param name="oSpools"></param>
		/// <returns></returns>
		public static bool IsSpoolsInSameNode(List<BusinessObject> oSpools)
		{
			List<object> listOfParent = new List<object>();
			foreach(var oSpool in oSpools)
			{
				Spool currSpool = oSpool as Spool;
				if (!listOfParent.Contains(currSpool.AssemblyParent))
				{
					listOfParent.Add(currSpool.AssemblyParent);
				}
			}

			if (listOfParent.Count != 1)
				return false;

			return true;
		}

		/// <summary>
		/// 生成一个留白数据
		/// </summary>
		public static SMgnt_SpoolInfo GeneralNullSMgntSpool(SMgnt_SpoolInfo oSMgntSpoolCopyFrom)
		{
			SMgnt_SpoolInfo oSMgntSpool = new SMgnt_SpoolInfo();
			string id = System.Guid.NewGuid().ToString();
			oSMgntSpool.Spool_oid = id;
			oSMgntSpool.CalculateCode = id;
			oSMgntSpool.Spool = oSMgntSpoolCopyFrom.Spool + "(留白)";
			oSMgntSpool.Zone = oSMgntSpoolCopyFrom.Zone;
			oSMgntSpool.Block = oSMgntSpoolCopyFrom.Block;
			oSMgntSpool.ParentAss = oSMgntSpoolCopyFrom.ParentAss;
			oSMgntSpool.ParentAss_oid = oSMgntSpoolCopyFrom.ParentAss_oid;
			oSMgntSpool.Block_oid = oSMgntSpoolCopyFrom.Block_oid;
			oSMgntSpool.PageNo = oSMgntSpoolCopyFrom.PageNo;
			oSMgntSpool.DrawNo = oSMgntSpoolCopyFrom.DrawNo;
			oSMgntSpool.Name = oSMgntSpoolCopyFrom.Name + "(留白)";
			oSMgntSpool.IsValid = 0;

			return oSMgntSpool;
		}

		/// <summary>
		/// 从oid获取bo对象
		/// </summary>
		/// <param name="sOid"></param>
		/// <returns></returns>
		public static BusinessObject GetBusinessObjectFromOid(string sOid)
		{
			TransactionManager transMgr = new TransactionManager();

			try
			{
				BOMoniker oBOMoniker = MiddleServiceProvider.SiteMgr.ActiveSite.ActivePlant.PlantModel.GetBOMonikerFromDbIdentifier(sOid);
				BusinessObject oBO = MiddleServiceProvider.SiteMgr.ActiveSite.ActivePlant.PlantModel.WrapSP3DBO(oBOMoniker);
				DateTime modifyTime = oBO.DateLastModified;//测试对象是否正常
				transMgr.Abort();
				return oBO;
			}
			catch
			{
				return null;
			}
		}

		/// <summary>
		/// 从Spool上获取对应的系统路径
		/// </summary>
		/// <param name="oBoOnSpool"></param>
		/// <returns></returns>
		public static string GetSystemPathFromSpool(BusinessObject oBoOnSpool)
		{
			BusinessObject oPipeline = GetPipeLineFromSpool(oBoOnSpool);
			if (oPipeline == null)
				return "";

			string sPath = "";


			return GetSystemPath(sPath, oPipeline);
		}

		public static string GetSystemPath(string sChildPath, BusinessObject oBo)
		{
			string sPath = oBo.ToString() + "\\" + sChildPath;

			ISystemChild oSystemChild = oBo as ISystemChild;
			if (oSystemChild != null && oSystemChild.SystemParent != null)
			{
				sPath = GetSystemPath(sPath, oSystemChild.SystemParent as BusinessObject);
			}

			return sPath;
		}

		public static BusinessObject GetPipeLineFromSpool(BusinessObject oBoOnSpool)
		{
			Spool oSpool = oBoOnSpool as Spool;
			if (oSpool != null)
			{
				foreach (var child in oSpool.AssemblyChildren)
				{
					PipeComponent oPipeComponent = child as PipeComponent;
					PipeStockPart oPipeStockPart = child as PipeStockPart;
					PipeSpecialty oPipeSpecialty = child as PipeSpecialty;
					if (oPipeComponent != null || oPipeStockPart != null || oPipeSpecialty != null)
					{
						//获取所在PipeRun
						BusinessObject oBo = child as BusinessObject;
						BusinessObject oPiperun = oBo.GetRelationship("OwnsParts", "Owner").TargetObjects[0];

						return GetPipeLineFromSystemBO(oPiperun);
					}
				}
			}

			return null;
		}

		public static BusinessObject GetPipeLineFromSystemBO(BusinessObject oBoOnSystemComponent)
		{
			if (oBoOnSystemComponent != null)
			{
				ISystemChild oSystemChild = oBoOnSystemComponent as ISystemChild;
				if (oSystemChild != null)
				{
					Pipeline oPipeline = oSystemChild.SystemParent as Pipeline;
					if (oPipeline != null)
					{
						return oPipeline;
					}
					else
					{
						if (oSystemChild.SystemParent != null)
						{
							GetPipeLineFromSystemBO(oSystemChild.SystemParent as BusinessObject);	
						}
						else
						{
							return null;
						}
					}
				}
			}

			return null;
		}
	}
}
